#ifndef E3D_VECTOR3_HPP
#define E3D_VECTOR3_HPP

#ifndef __cplusplus
#error "C++ required"
#endif

namespace e3d {

	template <typename real>
	class Vector3 {
	public:
		typedef real_traits<real> traits;
		typedef Vector3<real> vector_type;
	public:
		union {
			real v[3];
			struct {
				real x;
				real y;
				real z;
			};
		};

		Vector3(real x_ = traits::zero, real y_ = traits::zero,
			real z_ = traits::zero) : x(x_), y(y_), z(z_) {}

		Vector3(vector_type const & o) : x(o.x), y(o.y), z(o.z) {}

		vector_type & operator += (const vector_type & o) {
			x += o.x;
			y += o.y;
			z += o.z;
			return *this;
		}
		vector_type & operator -= (const vector_type & o) {
			x -= o.x;
			y -= o.y;
			z -= o.z;
			return *this;
		}
		template <typename real2>
		vector_type & operator *= (const real2 & o) {
			x *= o;
			y *= o;
			z *= o;
			return *this;
		}
		template <typename real2>
		vector_type & operator /= (const real2 & o) {
			x /= o;
			y /= o;
			z /= o;
			return *this;
		}
	};

	template <typename real>
	bool operator==(const Vector3<real> & a, const Vector3<real> & b) {
		return real_traits<real>::equals(a.x, b.x) &&
			real_traits<real>::equals(a.y, b.y) &&
			real_traits<real>::equals(a.z, b.z);
	}

	template <typename real>
	Vector3<real> operator+(const Vector3<real> & a, const Vector3<real> & b) {
		Vector3<real> r(a.x + b.x, a.y + b.y, a.z + b.z);
		return r;
	}

	template <typename real>
	Vector3<real> operator-(const Vector3<real> & a, const Vector3<real> & b) {
		Vector3<real> r(a.x - b.x, a.y - b.y, a.z - b.z);
		return r;
	}
}

#endif
